package com.atguigu.lease.web.app.service.impl;


import com.atguigu.lease.common.constant.RedisConstant;
import com.atguigu.lease.common.exception.LeaseException;
import com.atguigu.lease.common.result.ResultCodeEnum;
import com.atguigu.lease.common.utils.JwtUtil;
import com.atguigu.lease.common.utils.VerifyCodeUtil;
import com.atguigu.lease.model.entity.UserInfo;
import com.atguigu.lease.model.enums.BaseStatus;
import com.atguigu.lease.web.app.mapper.UserInfoMapper;
import com.atguigu.lease.web.app.service.LoginService;
import com.atguigu.lease.web.app.service.SmsService;
import com.atguigu.lease.web.app.vo.user.LoginVo;
import com.atguigu.lease.web.app.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private SmsService smsService;
    @Autowired
    private UserInfoMapper userInfoMapper;
    /**
     * 根据手机号获取短信验证码
     * @param phone
     */
    @Override
    public void getSMSCode(String phone) {
        //判断手机号是否为空
        if(!StringUtils.hasText(phone)){
            throw new LeaseException(ResultCodeEnum.APP_LOGIN_PHONE_EMPTY);
        }
        //设置存放在redis的key
        String codeKey= RedisConstant.APP_LOGIN_PREFIX+phone;
        //判断redis中是否存在key
        Boolean hasKey = stringRedisTemplate.hasKey(codeKey);
        if(hasKey){
            //能进来说明有key，获取key剩余时间
            Long expire = stringRedisTemplate.getExpire(codeKey);
            if(RedisConstant.APP_LOGIN_CODE_TTL_SEC-expire<RedisConstant.APP_LOGIN_CODE_RESEND_TIME_SEC){
                throw new LeaseException(ResultCodeEnum.APP_SEND_SMS_TOO_OFTEN);
            }
        }
        //到这说明，可以发送验证码，先获取验证码，再调用阿里云接口发送短信
        String verifyCode = VerifyCodeUtil.getVerifyCode(6);
        smsService.sendCode(phone,verifyCode);
        //再存入到redis中
        stringRedisTemplate.opsForValue().set(codeKey,verifyCode,RedisConstant.APP_LOGIN_CODE_TTL_SEC, TimeUnit.SECONDS);

    }

    /**
     * 设置token
     * @param loginVo
     * @return
     */
    @Override
    public String login(LoginVo loginVo) {
        //判断手机号是否输入
        if(!StringUtils.hasText(loginVo.getPhone())){
            throw new LeaseException(ResultCodeEnum.APP_LOGIN_PHONE_EMPTY);
        }
        //判断验证码是否为空
        if (!StringUtils.hasText(loginVo.getCode())){
            throw new LeaseException(ResultCodeEnum.APP_LOGIN_CODE_EMPTY);
        }
        //先从redis中获取验证码
        String codeInRedis = stringRedisTemplate.opsForValue().get(RedisConstant.APP_LOGIN_PREFIX + loginVo.getPhone());
        //如果通过键获取redis中值为空，说明验证码已经过期
        if(codeInRedis==null){
            throw new LeaseException(ResultCodeEnum.APP_LOGIN_CODE_EXPIRED);
        }
        //能到这说明有值，就比较获取验证码和redis中存储的验证码是否一致
        if(!codeInRedis.equals(loginVo.getCode())){
            throw new LeaseException(ResultCodeEnum.APP_LOGIN_CODE_ERROR);
        }
        //到这说明，验证码正确，我们需要判读此手机号是否是第一次注册，先根据手机查询数据库是都有用户信息，如果没有说明是第一次注册
        LambdaQueryWrapper<UserInfo> wrapper=new LambdaQueryWrapper<>();
        wrapper.eq(UserInfo::getPhone,loginVo.getPhone());
        UserInfo userInfo = userInfoMapper.selectOne(wrapper);
        if(userInfo==null){
            //到这说明此手机第一次登录，需要完成注册功能
            userInfo=new UserInfo();
            userInfo.setPhone(loginVo.getPhone());
            userInfo.setNickname("用户-"+loginVo.getPhone().substring(5));
            userInfo.setStatus(BaseStatus.ENABLE);
            userInfoMapper.insert(userInfo);
        }
        //到这说明不是第一次登录，需要判断改用户是否被禁用
        if(userInfo.getStatus()==BaseStatus.DISABLE){
            throw new LeaseException(ResultCodeEnum.APP_ACCOUNT_DISABLED_ERROR);
        }
        //设置token
        String token = JwtUtil.createToken(userInfo.getId(), userInfo.getPhone());
        return token;
    }

    /**
     * 根据ID获取登录用户信息
     * @param userId
     * @return
     */
    @Override
    public UserInfoVo info(Long userId) {
        UserInfo userInfo = userInfoMapper.selectById(userId);
        UserInfoVo userInfoVo = new UserInfoVo(userInfo.getNickname(),userInfo.getAvatarUrl());
        return userInfoVo;
    }
}
